#ifndef TINX_DEVICE_H
#define TINX_DEVICE_H

#include <tinx/list.h>

#define SECTOR_SIZE 512
#define BLOCK_SECTORS(block_size) (block_size / SECTOR_SIZE)

#define DIRECT_UP    0
#define DIRECT_DOWN  1

enum DEVICE_TYPE
{
    DEV_TYPE_NULL,
    DEV_TYPE_CHAR,
    DEV_TYPE_BLOCK
};

enum DEVICE_FLAG
{
    DEV_FLAG_CONSOLE,
    DEV_FLAG_KEYBOARD,
    DEV_FLAG_DISK,
    DEV_FLAG_PART,
    DEV_FLAG_RAMDISK,
    DEV_FLAG_SERIAL
};

enum REQ_CMD
{
    REQ_READ,
    REQ_WRITE
};

enum DEVICE_CMD
{
    DEV_CMD_SECTORS_COUNT,
    DEV_CMD_SECTORS_START,
    DEV_CMD_PART_TYPE,
};

typedef struct device_t
{
    char name[16];
    int type;
    int flag;
    u8 direct;
    list_t request_list;
    dev_t dev;
    dev_t parent;
    void *ptr;

    int (*write) (void *ptr, void *data, u32 count, u32 offset, u32 flags);
    int (*read) (void *ptr, void *data, u32 count, u32 offset, u32 flags);
    int (*ioctl) (void *ptr, int cmd, int arg);
} device_t;

int device_write(dev_t dev, void *data, int count, int offset, flag_t flags);
int device_read(dev_t dev, void *data, int count, int offset, flag_t flags);
int device_ioctl(dev_t dev, int cmd, int arg);
int device_request(dev_t dev, int cmd, void *data, u32 sectors, idx_t idx, flag_t flags);

dev_t device_find(flag_t flag, int idx);
device_t *device_get(dev_t dev);

dev_t device_create(
    int type, flag_t flag, dev_t parent, char *name, void *ptr,
    void *write, void *read, void *ioctl);

#endif